---
slug: react-redux #路径，不能重复
title: react-redux # 标题
authors: [] # 作者，在authors.yml配置
tags: [facebook, hello, docusaurus] # 标签，在tags.yml配置
toc_min_heading_level: 2 # 最小展示标题
toc_max_heading_level: 5 # 最大展示标题
---

:::tip
 **目前来看,更推荐`react-redux`+`redux-toolkit`** [redux-toolkit](redux-toolkit)
:::


## react-redux

> 简化redux操作

### Provider
> react-redux 自己内部创建了上下文对象，我们可以直接使用

`src/index.js`

```js
import React from 'react';
import ReactDOM from 'react-dom/client';
import reportWebVitals from './reportWebVitals';
import {App} from './views/App';
import store from "./store";
// highlight-next-line
import {Provider} from 'react-redux';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <>
    // highlight-start
      <Provider store={store}>
          <App/>
      </Provider>
    // highlight-end
  </>
)
reportWebVitals();
```

### 对应组件使用

#### connect

> 对于connect的使用需要调用connect函数后再次调用函数传递组件
> 对于组件的接收参数需要从props中接收

```jsx
import {connect} from 'react-redux';

const ReactReduxComp =  (props)=>{
    const {up,down} = props;
    return (
        <>
            <div>
                支持数:{up}
                反对数:{down}
            </div>
        </>
    )
}

export default connect(state=>state.vote,dispatch)(ReactReduxComp);

```

> 传递给组件的信息,接收两个参数`mapStateToProps`和`mapDispatchToProps`

##### `mapStateToProps`
> 传递给组件的属性，其实就是取公共状态的地方
```js
connect(state=>{
    //返回给组件的公共状态(对象形式)，组件需要从props中取值
    return {
        num:state.vote.num,
        down:state.vote.down
    }
})
```
---
或者简写，因为本身`state.vote`返回的也是对象形式

```jsx
connect(state=>state.vote)
```

##### `mapDispatchToProps`

> dispatch,变更行为派发(就是触发状态值改变)

> 把需要派发的任务当作属性传递给组件

**type得跟reducer里面定义的一样**

```jsx
export default connect(null,dispatch =>{
    return{
        upHandler(){
            dispatch({
                type:'vote-up',
            })
        },
        downHandler(){
            dispatch({
                type:'vote-down',
            })
        }
    }
})(ReduxStudy);
```

### 完整代码

#### 1.派发行为宏标识管理
> 把所有的type都统一到一个文件里

`src/store/action/action-types.js`

```js

//派发行为宏标识管理

export const VOTE_UP = "vote-up";

export const VOTE_DOWN = "vote-down";


export const PERSONAL_DELETE = "personal-delete";

export const PERSONAL_UPDATE = "personal-update";

export const PERSONAL_ADD = "personal-add";

```

---

#### 2.派发行为对象管理
> 把派发的行为对象统一管理起来

`src/store/action/vote-action.js`

```js
import * as Types from '../action-types';

/**
 * vote派发行为对象管理
 * @type {{vote_up(): {type: string}, vote_down(): {type: string}}}
 */
export const VoteAction = {
    vote_up(){
        return {
            type:Types.VOTE_UP
        }
    },
    vote_down(){
        return {
            type:Types.VOTE_DOWN
        }
    }
}

export default VoteAction;
```

---

#### 3.合并派发行为对象

`src/store/action/index.js`

```js
import VoteAction from "./vote-action";
const actions = {
    vote:VoteAction
}
export default actions;
```

---

**上面的几步只是封装而已,只是为了代码的简洁**

#### 4.定义单模块reducer
`src/store/reducer/voteReducer.js`

```jsx
const init = {
    up:1,
    down:1
}
export  default function VoteReducer(state = init, action) {
    switch (action.type) {
        case 'vote-up':
            return {
                ...state,up:state.up+1
            }
        case 'vote-down':
            return {
                ...state,down:state.down+1,
            }
    }
    return state;
}
```
---
#### 5.合并各个模块的reducer

`src/store/reducer/index.js`

```js
/**
 * 合并多个模块的reducer后创建一个总的reducer
 */
import {combineReducers} from "redux";
import VoteReducer from "./VoteReducer";


const reducer =   combineReducers({
        vote:VoteReducer
    })

export default reducer;
```
---
#### 6.将reducer给到store后得到我们真正需要的全局状态容器

**此时只是得到了合并后的reducer，还得把reducer给到store**

> 在这一步里面我们将合并后的reducer给到了createStore后得到了store

```js
import {createStore} from 'redux';
import combinedReducers from './reducer';

const store = createStore(combinedReducers);

export default store;
```

#### 7.将得到的store传递给跟组件(使用react-redux的Provider传递)
> `react-redux`的`Provider`可以取代我们的全局上下文对象,但是他 **只能** 传递store

```js
    import ReactDOM from 'react-dom/client';
    import reportWebVitals from './reportWebVitals';
    import '@ant-design/v5-patch-for-react-19';
    import {App} from './views/App';
    import store from "./store";
    import {Provider} from 'react-redux';
    const root = ReactDOM.createRoot(document.getElementById('root'));
    console.log("store", store);
    root.render(
      <>
          <Provider store={store}>
              <App/>
          </Provider>
      </>
    )

    // If you want to start measuring performance in your app, pass a function
    // to log results (for example: reportWebVitals(console.log))
    // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
    reportWebVitals();

```





#### 8.组件使用
```jsx
import React from 'react';
import {Button, Divider} from "antd";
import {connect} from 'react-redux';
import Actions from 'src/store/action';
const  ReduxStudy = function (props) {
    const {up,down,vote_up,vote_down} = props;
    return (
        <>
            <div className={'container'}>
                <h2>React是很棒的框架</h2>
                <div>
                    {up+down}
                </div>
            </div>
            <div>
                <div>
                    赞同票数:{up}
                </div>
                <div>
                    反对票数:{down}
                </div>
            </div>
            <Divider/>
            <Button onClick={vote_up}>
                投赞同票
            </Button>

            <Button onClick={vote_down}>
                投反对票
            </Button>
        </>
    )

};
//使用的是第三步的合并派发行为对象
export default connect(state=>state.vote,Actions.vote)(ReduxStudy);
```